package com.stephentuso.welcome;

import com.stephentuso.welcome.util.LogUtil;
import com.stephentuso.welcome.util.ResUtil;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.Text;
import ohos.agp.text.Font;
import ohos.app.Context;

import java.io.File;

/**
 * Created by stephentuso on 12/16/15.
 */
public class WelcomeUtils {

    /* package */ static final int NO_COLOR_SET = -1;

    private static final String TAG = WelcomeUtils.class.getName();

    public static String getKey(Class<? extends WelcomeAbility> abilityClass) {
        String key = null;

        try {
            key = (String) abilityClass.getMethod("welcomeKey").invoke(null);
            if (key.isEmpty()) {
                LogUtil.warn(TAG, "welcomeKey() from " + abilityClass.getSimpleName() + " returned an empty string. Is that an accident?");
            }
        } catch (NoSuchMethodException e) {
            //Method not found, don't worry about it
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (key == null) { key = ""; }
        return key;
    }

    /* package */ static boolean setTypeface(Text textView, String typefacePath, Context context) {
        if (typefacePath != null && !typefacePath.equals("")) {
            try {
                File file = ResUtil.resPathToFile(context, typefacePath);
                Font.Builder builder = new Font.Builder(file);
                textView.setFont(builder.build());
                return true;
            } catch (Exception e) {
                LogUtil.warn(TAG, "Error setting typeface");
            }
        }
        return false;
    }

    /* package */ static boolean isIndexBeforeLastPage(int index, int lastPageIndex, boolean isRtl) {
        return isRtl ? index > lastPageIndex : index < lastPageIndex;
    }

    /* package */ static int calculateParallaxLayers(Component view, boolean recursive) {
        if (recursive)
            return calculateParallaxLayersRecursively(view, 0);
        else
            return calculateParallaxLayers(view);
    }

    private static int calculateParallaxLayers(Component view) {
        if (view instanceof ComponentContainer) {
            ComponentContainer group = (ComponentContainer) view;
            return group.getChildCount();
        }
        return 1;
    }

    private static int calculateParallaxLayersRecursively(Component view, int startCount) {
        int count = startCount;
        if (view instanceof ComponentContainer) {
            ComponentContainer group = (ComponentContainer) view;
            for (int i = 0; i < group.getChildCount(); i++) {
                count = calculateParallaxLayersRecursively(group.getComponentAt(i), count);
            }
        } else {
            count++;
        }
        return count;
    }

    /**
     * Apply a parallax effect to a Component/ComponentContainer
     * @param view A Component or ComponentContainer
     * @param recursive Applies if {@code view} is a ComponentContainer. If true, this will recursively go through any child ViewGroups and apply the effect to their children.
     *                  If false, only {@code view}'s immediate children will move in the parallax effect
     * @param offsetPixels The current pixel offset for the page {@code view} is on.
     * @param startParallaxFactor The speed at which the first child should move. Negative values for slower, positive for faster.
     * @param parallaxInterval The difference in speed between the children.
     */
    public static void applyParallaxEffect(Component view, boolean recursive, int offsetPixels, float startParallaxFactor, float parallaxInterval) {
        if (recursive)
            applyParallaxEffectRecursively(view, offsetPixels, startParallaxFactor, parallaxInterval, 0);
        else
            applyParallaxEffectToImmediateChildren(view, offsetPixels, startParallaxFactor, parallaxInterval);
    }

    private static void applyParallaxEffectToImmediateChildren(Component view, int offsetPixels, float startParallaxFactor, float parallaxInterval) {
        if (view instanceof ComponentContainer) {
            ComponentContainer group = (ComponentContainer) view;
            for (int i = 0; i < group.getChildCount(); i++) {
                translateViewForParallaxEffect(group.getComponentAt(i), i, offsetPixels, startParallaxFactor, parallaxInterval);
            }
        } else {
            translateViewForParallaxEffect(view, 0, offsetPixels, startParallaxFactor, parallaxInterval);
        }
    }

    private static int applyParallaxEffectRecursively(Component view, int offsetPixels, float startParallaxFactor, float parallaxInterval, int index) {
        int nextIndex = index;
        if (view instanceof ComponentContainer) {
            ComponentContainer group = (ComponentContainer) view;
            for (int i = 0; i < group.getChildCount(); i++) {
                nextIndex = applyParallaxEffectRecursively(group.getComponentAt(i), offsetPixels, startParallaxFactor, parallaxInterval, nextIndex);
            }
        } else {
            translateViewForParallaxEffect(view, index, offsetPixels, startParallaxFactor, parallaxInterval);
            nextIndex++;
        }
        return nextIndex;
    }

    private static void translateViewForParallaxEffect(Component view, int index, int offsetPixels, float startParallaxFactor, float parallaxInterval) {
        view.setTranslationX(calculateParallaxOffsetAmount(index, offsetPixels, startParallaxFactor, parallaxInterval));
    }

    private static float calculateParallaxOffsetAmount(int index, int offsetPixels, float startParallaxFactor, float parallaxInterval) {
        return (startParallaxFactor + (index * parallaxInterval)) * -offsetPixels;
    }

}
